#!/bin/python
# -*- coding: utf-8 -*-
"""
Name: all_in_one.py
Author: harrybao
Mail: harrybao@123u.com
Time: 2021/06/30 20:57
Desc: 整合脚本
"""

import os
import getopt
import shutil
import sys
import platform
from sdk_packer import SDKPacker
from path_util import PathUtil
from global_var import *

global cwd
cwd = os.getcwd()
global abs_path
abs_path = os.path.abspath(os.path.dirname(__file__))
if cwd != abs_path:
    os.chdir(abs_path)

def build_service_idl(idl_list):
    """编译idl"""
    if len(idl_list) == 0:
        idl_list = g_idl_list

    PathUtil().go_to_service_box_repo_dir()

    for idl_name in idl_list:
        print('-- build_service_idl: {0}'.format(idl_name))
        os.system(
            'python3 repo.py -t cpp -a usr/guildservice/idl/{0}.idl'.format(idl_name))
        os.system('python3 repo.py -t cpp -b {0}'.format(idl_name))

    os.chdir(abs_path)

def build_service_lib(idl_list, build_type='Debug'):
    """编译lib库"""
    if len(idl_list) == 0:
        idl_list = g_idl_list
    if build_type != 'Debug' and build_type != 'Release':
        build_type = 'Debug'

    for idl_name in idl_list:
        src_path = '../src/{0}'.format(idl_name)
        if not PathUtil().check_path(src_path):
            continue

        os.system(
            'echo ' + '-- build_service_lib:{0} build_type:{1}'.format(idl_name, build_type))

        if platform.system() == "Windows":
            os.chdir('../win-proj/{0}'.format(idl_name))
            os.system(
                'cmake ../../src/{0} -G  "Visual Studio 16 2019" -A x64'.format(idl_name))
        else:
            os.chdir(src_path)
            os.system('mkdir -p build/{0}'.format(build_type))
            os.chdir('build/{0}'.format(build_type))
            os.system('cmake ../.. -G "Unix Makefiles"'.format(build_type))

        os.system('cmake --build . --config {0}'.format(build_type))
        os.chdir(abs_path)

def build_service_stub(idl_list, build_type='Debug'):
    """编译stub库"""
    if len(idl_list) == 0:
        idl_list = g_idl_list

    if build_type != 'Debug' and build_type != 'Release':
        build_type = 'Debug'

    for idl_name in idl_list:
        for service_name in g_service_dic[idl_name]:
            dest_path = '../../../tmp/{0}/stub/{1}'.format(
                idl_name, service_name)
            if not os.path.exists(dest_path):
                print('path not exist: {0}'.format(dest_path))
                continue
            os.system(
                'echo -- build_service_stub:{0} build_type:{1}'.format(idl_name, build_type))
            os.chdir(dest_path)
            if platform.system() == "Windows":
                os.system(
                    'cmake . -G  "Visual Studio 16 2019" -A x64'.format(build_type))
            else:
                os.system('cmake . -G "Unix Makefiles"'.format(build_type))
            os.system('cmake --build . --config {0}'.format(build_type))
            os.chdir(abs_path)

def update_service_impl(idl_list):
    """更新impl"""
    if len(idl_list) == 0:
        idl_list = g_idl_list
    
    path_util = PathUtil()
    os_name = platform.system()

    for idl_name in idl_list:
        if g_service_dic.get(idl_name) == None:
            print('idl_name error: {0}'.format(idl_name))
            continue
        for service_name in g_service_dic[idl_name]:
            src_path = os.path.join(path_util.guild_service_tools_path, 'usr/impl/{0}/{1}'.format(idl_name, service_name))
            dst_path = os.path.join(path_util.service_box_repo_path, 'usr/impl/{0}/{1}'.format(idl_name, service_name))
            if not path_util.check_path(src_path):
                continue
            if not path_util.check_path(dst_path):
                continue
            print('-- copy {0} {1}'.format(src_path, dst_path))
            for file_name in os.listdir(src_path):
                cur_path = os.path.join(src_path, file_name)
                if os.path.isdir(cur_path):
                    continue
                shutil.copy2(os.path.join(src_path, file_name), dst_path)
            shutil.copy2(os.path.join(src_path, os_name, 'CMakeLists.txt'), dst_path)

def backup_service_impl(idl_list):
    """备份impl"""
    if len(idl_list) == 0:
        idl_list = g_idl_list
    
    path_util = PathUtil()
    os_name = platform.system()

    for idl_name in idl_list:
        if g_service_dic.get(idl_name) == None:
            print('idl_name error: {0}'.format(idl_name))
            continue
        for service_name in g_service_dic[idl_name]:
            src_path = os.path.join(path_util.service_box_repo_path, 'usr/impl/{0}/{1}'.format(idl_name, service_name))
            dst_path = os.path.join(path_util.guild_service_tools_path, 'usr/impl/{0}/{1}'.format(idl_name, service_name, os_name))
            if not path_util.check_path(src_path):
                continue
            if not path_util.check_path(dst_path):
                continue
            print('-- copy {0} {1}'.format(src_path, dst_path))
            for file_name in os.listdir(src_path):
                cur_path = os.path.join(src_path, file_name)
                if os.path.isdir(cur_path):
                    continue
                if file_name == 'CMakeLists.txt':
                    continue
                shutil.copy2(os.path.join(src_path, file_name), dst_path)
            shutil.copy2(os.path.join(src_path, 'CMakeLists.txt'), os.path.join(dst_path, os_name))

def update_service_idl():
    """更新idl"""
    if platform.system() == "Windows":
        os.chdir('windows')
        os.system('update_idl.bat')
    else:
        os.chdir('linux')
        os.system('sh update_idl.sh')
    os.chdir(abs_path)

def build_demo(proj_name, build_type='Debug'):
    """编译demo"""
    dest_path = ''

    if platform.system() == "Windows":
        dest_path = '../win-proj/demo/{0}'.format(proj_name)
    else:
        dest_path = '../demo/{0}'.format(proj_name)

    if not os.path.exists(dest_path):
        print('path not exists: {0}'.format(dest_path))
        return

    os.chdir(dest_path)

    if platform.system() == "Windows":
        os.system(
            'cmake ../../../demo/{0} -G "Visual Studio 16 2019" -A x64'.format(proj_name))
    else:
        os.system('mkdir build')
        os.chdir('build')
        os.system('cmake .. -G "Unix Makefiles"'.format(build_type))

    os.system('cmake --build . --config {0}'.format(build_type))
    os.chdir(abs_path)

def clean_temp_files():
    """清除生成文件"""
    for idl_name in g_idl_list:
        if platform.system() == "Windows":
            # os.chdir('windows')
            os.system('rd /S /Q ..\..\..\src\{0}'.format(idl_name))
            os.system('rd /S /Q ..\..\..\src\proxy\{0}'.format(idl_name))
            os.system('rd /S /Q ..\..\..\src\stub\{0}'.format(idl_name))
            os.system('rd /S /Q ..\..\..\src\include\{0}'.format(idl_name))
            os.system('del /q ..\..\..\src\idl\{0}.idl'.format(idl_name))
            os.system('rd /S /Q ..\..\..\\tmp\{0}'.format(idl_name))
            os.system('rd /S /Q ..\..\..\\usr\impl\{0}'.format(idl_name))
            os.system('rd /S /Q ..\..\..\lib\stub\{0}'.format(idl_name))
            os.system('rd /S /Q ..\..\..\lib\proxy\{0}'.format(idl_name))
            os.system('rd /S /Q ..\..\..\lib\{0}'.format(idl_name))
            # os.system('clean_tmp_files.bat')
        else:
            os.system(
                'sh {0}/tools/linux/clean_tmp_files.sh'.format(PathUtil().guild_service_root_path))
    os.chdir(abs_path)

def publish(idl_list, build_type='Debug'):
    """发布"""
    if len(idl_list) == 0:
        idl_list = g_idl_list

    path_util = PathUtil()

    dst_path = path_util.service_box_publish_path
    if platform.system() == 'Windows':
        dst_path = os.path.join(dst_path, build_type)

    if not path_util.check_path(dst_path):
        return

    for idl_name in idl_list:
        if g_service_dic.get(idl_name) == None:
            print('idl_name error: {0}'.format(idl_name))
            continue

        if platform.system() == "Windows":
            src_path = '..\..\..\lib\stub\{0}\{1}\{2}\lib{3}.so'.format(
                idl_name, g_service_dic[idl_name][0], build_type, g_service_dic[idl_name][0])

            if not path_util.check_path(src_path):
                continue
            
            print('-- copy {0} {1}'.format(src_path, dst_path))
            shutil.copy(src_path, dst_path)
        else:
            src_path = '../../../lib/stub/{0}/{1}/lib{2}.so'.format(
                idl_name, g_service_dic[idl_name][0], g_service_dic[idl_name][0])

            if not path_util.check_path(src_path):
                continue

            print('-- copy {0} {1}'.format(src_path, dst_path))
            os.system('cp {0} {1}'.format(src_path, dst_path))

def pack(idl_list=g_idl_list):
    """打包"""
    SDKPacker(PathUtil().guild_service_package_path, g_sdk_project_name,
              g_sdk_name, 'cpp', g_sdk_version).pack(idl_list)

def clean_package():
    """清理package目录"""
    path_util = PathUtil()
    path_util.remove_path(os.path.join(path_util.guild_service_package_path, 'doc'), False)
    path_util.remove_path(os.path.join(path_util.guild_service_package_path, 'include'), False)
    path_util.remove_path(os.path.join(path_util.guild_service_package_path, 'info'), False)
    path_util.remove_path(os.path.join(path_util.guild_service_package_path, 'lib'), False)
    path_util.remove_path(os.path.join(path_util.guild_service_package_path, 'protobuf'), False)
    path_util.remove_path(os.path.join(path_util.guild_service_package_path, 'proxy'), False)
    path_util.remove_path(os.path.join(path_util.guild_service_package_path, 'stub'), False)

def build_mock(idl_list, build_type='Debug'):
    """构建mock"""
    if len(idl_list) == 0:
        idl_list = g_idl_list
    if build_type != 'Debug' and build_type != 'Release':
        build_type = 'Debug'
    
    os.chdir(os.path.join(PathUtil().service_box_root_path, 'src/repo'))

    for idl_name in idl_list:
        os.system('echo -- build_mock: {0}'.format(idl_name))
        os.system('python3 repo.py -t cpp --mock {0}'.format(idl_name))

def build_test(build_type='Debug'):
    """构建测试"""
    path_util = PathUtil()
    src_path = os.path.join(path_util.guild_service_root_path, 'test/src')
    if not path_util.check_path(src_path):
        return

    if platform.system() == "Windows":
        build_path = os.path.join(path_util.guild_service_root_path, 'win-proj/guildserviceunittest')
        if not path_util.check_path(build_path):
            return
        os.chdir(build_path)
        os.system(
            'cmake {0} -G "Visual Studio 16 2019" -A x64'.format(src_path))

        os.system('cmake --build {0} --config {1}'.format(build_path, build_type))
    else:
        build_path = os.path.join(src_path, 'build', build_type)
        os.mkdir(build_path)
        if not path_util.check_path(build_path):
            return
        os.system('cmake {0} -G "Unix Makefiles" --build {1}'.format(src_path, build_path))
        os.system('cmake --build {0} --config {1}'.format(build_path, build_type))

# 使用方式
def usage():
    print("")
    print("    -h,--help                               使用说明")
    print("    -i,--idl                                <idl文件名>")
    print("    --build_idl                             根据idl文件生成代码")
    print("    --build_lib                             编译无rpc的静态库")
    print("    --build_stub                            编译有rpc的动态库")
    print("    --update_impl                           覆盖更新rpc生成的impl文件")
    print("    --backup_impl                           覆盖备份rpc生成的impl文件")
    print("    --clean_tmp                             删除idl生成的代码")
    print("    --build_demo                            编译demo")
    print("    --publish                               发布")
    print("    --pack                                  打包")
    print("    --clean_package                         清理package目录")
    print("    --build_mock                            构建mock")
    print("    --build_type                            编译类型")
    print("    --build_test                            构建测试")


def parse_options():
    try:
        opts, args = getopt.getopt(sys.argv[1:], '-h-i:',
                                   ['help', 'idl=', 'build_idl', 'build_lib', 'build_stub',
                                    'update_impl', 'backup_impl', 'update_idl', 'clean_tmp', 'build_demo=',
                                    'publish', 'pack', 'clean_package', 'build_mock', 'build_type=', 'build_test'])
    except getopt.GetoptError as e:
        print(str(e))
        return

    idl_list = []
    build_type = 'Debug'

    if len(opts) == 0:
        usage()
        return

    for opt, value in opts:
        if opt in ('-h', '--help'):
            usage()
            return
        if opt in ('-i', '--idl'):
            idl_list.append(value)
            continue
        if opt in ('--build_type'):
            if value == 'Debug' or value == 'Release':
                build_type = value
            else:
                print('build_type invalid: [Debug|Release]')
            continue

    for opt, value in opts:
        if opt in ("--build_idl"):
            build_service_idl(idl_list)
        if opt in ("--build_lib"):
            build_service_lib(idl_list, build_type)
        if opt in ("--build_stub"):
            build_service_stub(idl_list, build_type)
        if opt in ("--update_impl"):
            update_service_impl(idl_list)
        if opt in ("--backup_impl"):
            backup_service_impl(idl_list)
        if opt in ("--update_idl"):
            update_service_idl()
        if opt in ("--clean_tmp"):
            clean_temp_files()
        if opt in ('--build_demo'):
            build_demo(value, build_type)
        if opt in ('--publish'):
            publish(idl_list, build_type)
        if opt in ('--pack'):
            pack()
        if opt in ('--clean_package'):
            clean_package()
        if opt in ('--build_mock'):
            build_mock(idl_list)
        if opt in ('--build_test'):
            build_test()


if __name__ == "__main__":
    parse_options()
    if cwd != abs_path:
        os.chdir(cwd)
